package com.alex.util.threads;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;

/**
 * @author alex
 */
public class ThreadPoolHolder {

    private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolHolder.class);

    private static final int THREAD_POOL_SIZE = 40;

    private static final long KEEP_ALIVE_TIME = 60L;

    public static final ExecutorService THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(THREAD_POOL_SIZE, THREAD_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>()) {

        /**
         * 覆盖这个方法是为了解决ThreadPoolExecutor#submit方法吞掉了线程中的异常的问题
         * 如果调用ThreadPoolExecutor#execute则不会出现这个问题
         *
         * see https://imxylz.com/blog/2013/08/02/handling-the-uncaught-exception-of-java-thread-pool/
         * see https://stackoverflow.com/questions/4016091/what-is-the-difference-between-submit-and-execute-method-with-threadpoolexecutor
         */
        @Override
        protected void afterExecute(Runnable r, Throwable t) {

            super.afterExecute(r, t);

            //submit提交的任务异常在这里处理
            if (t == null && r instanceof Future<?>) {
                try {
                    Future<?> future = (Future<?>) r;
                    if (future.isDone()) {
                        future.get();
                    }
                } catch (CancellationException ce) {
                    t = ce;
                } catch (ExecutionException ee) {
                    t = ee.getCause();
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt(); // ignore/reset
                }
            }

            //execute提交的任务异常在这里处理
            if (t != null) {
                LOGGER.error(t.getMessage(), t);
            }
        }
    };
}
